import Utils from "../../../../Utils";
import DestructibleFacility from "../../../facility/DestructibleFacility";
import DefenseCannon from "../../../facility/priveteFacility/DefenseCannon";
import MainHome from "../../../facility/priveteFacility/MainHome";
import { FacilityType, Gain } from "../../../info/GameEnum";
import { Global } from "../../../info/Global";
import { Location } from "../../../info/Predefine";
import GameManager from "../../../manager/GameManager";
import { AiEnvironment } from "../AiGameAction";
import { DecisionNode } from "../DecisionTree";

/**
 * 防守威胁
 */
export default class DecisionDefense extends DecisionNode {

    /**
     * 附近是否有平头哥
     * 得分
     */
    environment: AiEnvironment & { allFacility: DestructibleFacility[][] };

    constructor(environment: any) {
        super(environment);
        this.childDecisionNodes.push(new DecisionBuildDefenseCannon(environment));
        this.childDecisionNodes.push(new DecisionUpgradeDefenseCannon(environment));
        this.childDecisionNodes.push(new DecisionHealthLevelUp(environment));
        this.childDecisionNodes.push(new DecisionRepairMainhomeextends(environment));
        this.childDecisionNodes.push(new DecisionDefenseLevelUp(environment));
        this.childDecisionNodes.push(new DecisionArtilleryDamageBonusLevelUp(environment));
    }

    /**
     * 主基地血量
     * 平头哥数量
     * 我的设施被攻击
     * 威胁值
     * @returns 
     */
    evaluate(): number {
        let score = 0;
        if (this.environment.gameTime > 120) {
            score += 20;
        }

        let selfHome = this.environment.player.facilityArr[FacilityType.主基地][0]
        let hpRate = selfHome.currentHp / selfHome.maxHp;
        score += Math.ceil(60 - hpRate * 60);
        if (GameManager.instance.badgerParent.childrenCount) {
            score += 50;
        }

        let betterThanMe = 0;
        this.environment.enemyThreatValue.forEach(value => {
            value >= this.environment.selfThreatValue && betterThanMe++;
        })

        score += betterThanMe * 30;

        return score;
    }

    execute(): number {
        this.environment.allFacility = this.environment.player.facilityArr;
        return super.execute();
    }
}


/**
 * 建造近防炮
 */
class DecisionBuildDefenseCannon extends DecisionNode {

    environment: AiEnvironment & {
        canUsedLocation: Location[][]; allFacility: DestructibleFacility[][]
    };

    evaluate(): number {
        if (!this.environment.player.checkFacilityCondition(FacilityType.近防炮).every(item => item)) return 0;
        let canUsedLocation = this.environment.player.getSpaceBySize(1);
        if (!canUsedLocation.length) return 0;//位置不够

        let score = 0;
        this.environment.canUsedLocation = canUsedLocation;

        let cannonCount = this.environment.player.facilityArr[FacilityType.近防炮].length;

        //如果有平头哥，没有近防炮
        if (cannonCount == 0) {
            score += 50;
            if (GameManager.instance.badgerParent.childrenCount) {
                score += 50;
            }
        }

        //近防炮数量越多 分数越低 提供 60分
        score += 60 - (cannonCount / 8 * 60)
        //现有资源是所需资源的两倍 提供40分 否则 20分
        let price = this.environment.player.getPrice(FacilityType.近防炮);
        if (this.environment.player.diamond > price.diamond * 2 && this.environment.player.oil > price.oil * 2) {
            score += 40;
        } else {
            score += 20;
        }
        return score;
    }

    execute(): number {
        //避免数据太大，使用采样策略，超过二十个则随机采样20个
        this.environment.canUsedLocation = Utils.shuffleArray(this.environment.canUsedLocation, 20);
        let mainhomeLocation = Utils.getRandomChoose(this.environment.player.facilityArr[FacilityType.主基地][0].locations);
        let locationScores = this.environment.canUsedLocation.map(locations => {
            //距离主基地越近越加分
            let score = 1,
                location = locations[0],
                distanse = Math.abs(location.locationX - mainhomeLocation.locationX) + Math.abs(location.locationY - mainhomeLocation.locationY);
            distanse = Math.min(10, distanse);
            score += (10 - distanse) / 10 * 100;
            return score;
        })
        let randomIndex = Utils.getRandomIndexByProbability(locationScores);
        this.environment.player.addFacility(FacilityType.近防炮, this.environment.canUsedLocation[randomIndex]);
        return 0;
    }

}


/**
 * 升级近防炮
 */
class DecisionUpgradeDefenseCannon extends DecisionNode {

    environment: AiEnvironment & {
        ableCannons: DefenseCannon[];
        allFacility: DestructibleFacility[][]
    };

    evaluate(): number {
        let score = 0;
        let cannons = this.environment.allFacility[FacilityType.近防炮];
        let ableCannons = cannons.filter(item => {
            let price = Global.FacilityInfo[FacilityType.近防炮].每等级升级要求[item.level];
            return price && this.environment.player.checkEnoughMoney(price);
        }) as DefenseCannon[]
        if (!ableCannons.length) return 0;

        this.environment.ableCannons = ableCannons;
        //近防炮数量越多 分数越高
        let count = cannons.length
        count = Math.min(5, count);
        score += count * 20;
        return score;
    }

    execute(): number {
        //离主基地越近，级别越高，血量越高
        let scores: number[] = [];
        let mainhomeLocation = GameManager.instance.getMapLocation(this.environment.player.facilityArr[FacilityType.主基地][0].node.position);
        this.environment.ableCannons.forEach(item => {
            let score = 0;
            let facLocation = item.locations[0];
            //距离带来40分 10格 0分  0格 40分
            let distanse = Math.abs(facLocation.locationX - mainhomeLocation.locationX) + Math.abs(facLocation.locationY - mainhomeLocation.locationY);
            distanse = Math.min(10, distanse);
            score += (10 - distanse) / 10 * 40;
            //级别带来30分
            score += item.level / (Global.FacilityInfo[FacilityType.近防炮].每等级升级要求.length - 1) * 30
            //血量带来30分
            score += item.currentHp / item.maxHp * 30
            scores.push(Math.ceil(score));
        })

        let randomIndex = Utils.getRandomIndexByProbability(scores);
        this.environment.ableCannons[randomIndex].levelUp();
        return 0;
    }

}



/**
 * 建筑血量升级
 */
class DecisionHealthLevelUp extends DecisionNode {

    environment: AiEnvironment & {
        allFacility: DestructibleFacility[][]
    };

    evaluate(): number {
        if (!this.environment.player.checkGainCondition(Gain.建筑血量升级).every(item => item)) return 0;
        let score = 0;
        //设施数量带来40分
        let facilityCount = this.environment.allFacility.length;
        score += Math.ceil(Math.min(6, facilityCount) / 6 * 40);

        //设施血量比例 带来 60分
        let allMaxHp = 0, allCurrentHp = 0;
        this.environment.allFacility.forEach((item: DestructibleFacility[]) => {
            item.forEach((fac: DestructibleFacility) => {
                allMaxHp += fac.maxHp;
                allCurrentHp += fac.currentHp;
            })
        })
        let rate = allCurrentHp / allMaxHp;
        score += Math.ceil(60 - (rate * 60));
        return score;
    }

    execute(): number {
        this.environment.player.buildingHealthLevelUp();
        return 0;
    }

}


/**
 * 建筑防御升级
 */
class DecisionDefenseLevelUp extends DecisionNode {

    environment: AiEnvironment & { allFacility: DestructibleFacility[][] };

    evaluate(): number {
        if (!this.environment.player.checkGainCondition(Gain.建筑防御升级).every(item => item)) return 0;
        let score = 0;
        //设施数量带来40分
        let facilityCount = this.environment.allFacility.length;
        score += Math.ceil(Math.min(6, facilityCount) / 6 * 40);

        //设施血量比例 带来 60分
        let allMaxHp = 0, allCurrentHp = 0;
        this.environment.allFacility.forEach((item: DestructibleFacility[]) => {
            item.forEach((fac: DestructibleFacility) => {
                allMaxHp += fac.maxHp;
                allCurrentHp += fac.currentHp;
            })
        })
        let rate = allCurrentHp / allMaxHp;
        score += Math.ceil(60 - (rate * 60));
        return score;
    }

    execute(): number {
        this.environment.player.buildingDefenseLevelUp();
        return 0;
    }

}

/**
 * 近防炮攻击力升级
 */
class DecisionArtilleryDamageBonusLevelUp extends DecisionNode {

    environment: AiEnvironment;

    evaluate(): number {
        if (!this.environment.player.checkGainCondition(Gain.近防炮攻击升级).every(item => item)) return 0;
        let bonusCount = this.environment.player.facilityArr[FacilityType.近防炮].length;
        if (bonusCount <= 2) return 10;
        if (bonusCount >= 6) return 100;

        let score = 0;
        switch (bonusCount) {
            case 3:
                score = 20
                break;
            case 4:
                score = 50
                break;
            case 5:
                score = 80
                break;
        }
        return score;
    }

    execute(): number {
        this.environment.player.artilleryDamageBonusLevelUp();
        return 0;
    }
}

/**
 * 维修基地
 */
class DecisionRepairMainhomeextends extends DecisionNode {

    environment: AiEnvironment;

    evaluate(): number {
        if (!this.environment.player.checkGainCondition(Gain.维修基地).every(result => result)) return 0;
        let mainhome: MainHome = <MainHome>this.environment.player.facilityArr[FacilityType.主基地][0];
        let rate = mainhome.currentHp / mainhome.maxHp;
        if (rate >= 0.7) {
            return 10;
        }
        if (rate <= 0.3) {
            return 100;
        }
        return (rate - 0.3) / (0.7 - 0.3) * 100
    }

    execute(): number {
        this.environment.player.repairMainhome();
        return 0;
    }
}

